package artibella.ui.scrolls
{
	import artibella.ui.scrolls.IDimensionable;
	import artibella.IDisposable;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import pixelbreaker.ui.osx.MacMouseWheel;
	
	/**
	 * ...
	 * @author pbordachar
	 */
	
	public class ScrollBox extends Sprite implements IDisposable
	{
		private var _largeur:int;
		private var _hauteur:int;
		
		private var _container:Sprite;
		private var _masque:Sprite;
		private var _zone:Sprite;
		private var _scrollingTool:ScrollBar;
		private var _containerHeight:int;
		
		private var _ratio:Number = 1.0;
		private var _moving:Boolean = false;
		private var _dest:int;

		
		public function ScrollBox( l:int, h:int ) 
		{
			_largeur = l;
			_hauteur = h;
			
			_init();
		}
		
		private function _init():void
		{
			_container = new Sprite();
			addChild( _container );
			
			_masque = new Sprite();
			_masque.graphics.beginFill( 0xFF0000 );
			_masque.graphics.drawRect( 0, 0, _largeur, _hauteur );
			_masque.graphics.endFill();
			addChild( _masque );
			
			_container.mask = _masque;
			
			_zone = new Sprite();
			_zone.graphics.beginFill( 0xFF0000 );
			_zone.graphics.drawRect( 0, 0, _largeur, _hauteur );
			_zone.graphics.endFill();
			_zone.alpha = 0;
			addChildAt( _zone, 0 );
		}
		
		// - - -
		
		public function setScrollingTool( c:ScrollBar ):void
		{
			_scrollingTool = c;
		}
		
		public function setContent( c:DisplayObject ):void
		{
			while ( _container.numChildren > 0 ) _container.removeChildAt( 0 );
			
			_removeEnterFrameHandler();
			
			_container.x = 0;
			_container.y = 0;
			_container.addChild( c );
			
			if( c is IDimensionable ){
				_containerHeight = ( c as IDimensionable ).getHeight() + 5;
			} else {
				_containerHeight = _container.height + 5;
			}
			
			_ratio = _containerHeight / _hauteur;
			
			if ( _scrollingTool != null ) _scrollingTool.updatedContent( _ratio );
			
			if ( _ratio > 1 ) _setMouseWheel();
		} 
		
		private function _setMouseWheel():void
		{
			if ( stage ) MacMouseWheel.setup( stage );
			
			addEventListener( MouseEvent.MOUSE_WHEEL, _onMouseWheel );
		}
		
		private function _onMouseWheel( e:MouseEvent ):void
		{
			var posY:int = _container.y;
			posY += e.delta * 5;
			setLocation( posY );
		}
		
		// - - -
		
		public function getLocation():int 
		{
			return _moving ? _dest : int( _container.y );
		}
		
		public function setLocation( posY:int ):void 
		{
			_removeEnterFrameHandler();
			
			var posMin:int = - ( _containerHeight - _hauteur );
			
			if ( posY > 0 ) {
				posY = 0;
			} else if ( posY < posMin ) {
				posY = posMin;
			}
			
			_container.y = posY;
			
			if ( _scrollingTool != null ) {
				
				var percent:Number = posY / posMin;
				_scrollingTool.setScrollerLocation( percent );
			}
		}
		
		// - - -
		
		public function setRelativeLocation( percent:Number, smoothed:Boolean ):void 
		{
			var posMin:int = - ( _containerHeight - _hauteur );
			var destY:int = posMin * percent;
			
			if( !smoothed ){
				_container.y = destY;
			} else {
				_smoothMove( destY );
			}
		}
		
		private function _smoothMove( destY:int ):void
		{
			_moving = true;
			_dest = destY;
			
			if ( !_container.hasEventListener( Event.ENTER_FRAME ) ){
				_container.addEventListener( Event.ENTER_FRAME, _enterFrameHandler );
			}
		}
		
		private function _enterFrameHandler( e:Event ):void
		{
			if ( Math.abs( _container.y - _dest ) > 1 ) {
				_container.y += ( _dest - _container.y ) / 3;
			} else {
				_moving = false;
				_container.y = _dest;
				_container.removeEventListener( Event.ENTER_FRAME, _enterFrameHandler );
			}
		}
		
		private function _removeEnterFrameHandler():void
		{
			if ( _moving ) {
				_moving = false;
				_container.removeEventListener( Event.ENTER_FRAME, _enterFrameHandler );
			}
		}
		
		// - - -
		
		public function get ratio():Number
		{
			return _ratio;
		}
		
		// - - -
		
		public function dispose():void
		{
			if ( hasEventListener(MouseEvent.MOUSE_WHEEL ) ) {
				removeEventListener(MouseEvent.MOUSE_WHEEL, _onMouseWheel);
			}
			
			_removeEnterFrameHandler();
			
			_container = null;
			_masque = null;
			_scrollingTool = null;
		}
	}
}